home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / TURBOPASCAL WIN / OWLDEMOS.PAK / OLEOBJ.PAS < prev    next >
Pascal/Delphi Source File  |  1992-06-08  |  23KB  |  725 lines

  1. {***************************************************}
  2. {                                                   }
  3. {   Turbo Pascal for Windows                        }
  4. {   Windows 3.1 OLE Server Demonstration Program    }
  5. {               OLE Object Unit                     }
  6. {                                                   }
  7. {   Copyright (c) 1992 by Borland International     }
  8. {                                                   }
  9. {***************************************************}
  10.  
  11. { This unit implements the actual OLE Object.  The Object rep-
  12.   resents the lowest level of interaction between the Client and
  13.   Server: the Object is the actual information the Client is after.
  14.  
  15.   For this demo, the only supported object is a simple blue graphic
  16.   that can be one of three shapes: a circle, a square, or a
  17.   rectangle.
  18.  
  19.   Although we have embedded the native data in the ole object, you might
  20.   not want to do this.  Rather than integrate OLE with your app you
  21.   should treat OLE as a protocol that sits on top of your app and allows
  22.   other applications access to your server's data.  Instead of embedding
  23.   the data in the OLE object have the OLE object contain a pointer to the
  24.   native data.
  25.  
  26.   Note: To compile the OLE Server demo, set Compile|Primary File to OLESERVR.PAS
  27. }
  28.  
  29. unit OleObj;
  30.  
  31. interface
  32.  
  33. uses WinTypes, WObjects, Ole, OleTypes;
  34.  
  35. type
  36.  
  37. { Type which defines the types of actions that the server can perform on
  38.   an object.
  39. }
  40.   TVerb = (VerbEdit, VerbPlay);
  41.  
  42. { The following record types represent the Object within
  43.   the OLE library.  It is based on the standard structure
  44.   defined in Ole.pas, and adds one field to provide access
  45.   back to the TPW object which represents it.
  46. }
  47.   POleObjectObj = ^TOleObjectObj;
  48.  
  49.   PAppObject = ^TAppObject;
  50.   TAppObject = record
  51.     OleObject: TOleObject;
  52.     Owner    : POleObjectObj;
  53.   end;
  54.  
  55. { TOleObjectObj }
  56.  
  57. { This object represents the OLE Object, wrapping useful
  58.   behaviors around the basic TOleObject structure that is
  59.   used within OLE to represent an object.  This structure
  60.   is represented by the AppObject data field, which is of
  61.   the TAppObject type defined in oleservr.pas, and which
  62.   includes an additional field which points back to Self
  63.   so that our callback functions can reference this object.
  64. }
  65.   TOleObjectObj = object(TObject)
  66.     AppObject : TAppObject;
  67.     Native    : TNative;
  68.     IsReleased: Boolean;  { True if Release method has been called }
  69.     Clients   : array[0..MaxLinks] of POleClient;  { nil terminated list of client(s) }
  70.                                                    { we are linked to                 }
  71.     constructor Init;
  72.     constructor Load(var S: TStream);
  73.  
  74.     procedure AddClientLink(OleClient: POleClient); virtual;
  75.     procedure Draw(ADC: HDC); virtual;
  76.     function  GetType: TNativeType; virtual;
  77.     procedure ObjectChanged; virtual;
  78.     procedure SetType(NewType: TNativeType); virtual;
  79.     procedure Store(var S: TStream); virtual;
  80.  
  81.     { Routines to build the various clipboard formats that are required for
  82.       an OLE server.  Your routine might provide routines for additional 
  83.       formats such as TEXT, RTF, and DIB.
  84.     }
  85.     function GetNativeData:      THandle; virtual;       
  86.     function GetLinkData:        THandle; virtual;        
  87.     function GetBitmapData:      HBitmap; virtual;       
  88.     function GetMetafilePicture: THandle; virtual;
  89.   end;
  90.  
  91. { TOleObjectObj stream registration record }
  92.  
  93. const
  94.   ROleObjectObj: TStreamRec = (
  95.     ObjType: 888;
  96.     VmtLink: Ofs(TypeOf(TOleObjectObj)^);
  97.     Load   : @TOleObjectObj.Load;
  98.     Store  : @TOleObjectObj.Store
  99.   );
  100.  
  101. function TOleObjectObj_InitVTBL(Inst: THandle): Boolean;
  102.  
  103. implementation
  104.  
  105. uses WinProcs, Strings, Server, OleApp, ServrWin;
  106.  
  107. { Global variables }
  108.  
  109. var
  110.   OleObjectVtbl: TOleObjectVtbl;
  111.  
  112.  
  113. { Object Callback Procedures }
  114.  
  115. { NOTE:
  116.   The first parameter to each callback is a pointer to the TOleObject
  117.   structure that defines this object.  In each case, we know that it
  118.   will really be a pointer to a TAppObject record, which includes a
  119.   pointer to the Pascal object which owns the TOleObject record.  We
  120.   can therefore use a typecast to access that object, and thus find our
  121.   way back to Self.
  122. }
  123.  
  124. { Handles the QueryProtocol callback.  The server library is trying to
  125.   determine which protocols we support.  'Protocol' will either be 
  126.   'StdFileEditing' or 'StdExecute'.  If we don't support the protocol 
  127.   then we should return nil.  Since we don't support 'StdFileExecute' 
  128.   we return nil in that case.
  129. }    
  130. function QueryProtocol(Self: POleObject; Protocol: PChar): Pointer; export;
  131. begin
  132.   if StrIComp(Protocol, 'StdFileEditing') = 0 then
  133.     QueryProtocol := Self
  134.   else
  135.     QueryProtocol := nil;
  136. end;
  137.  
  138. { Handles the Release callback.  This gets called when the library wants
  139.   to inform us that we have no more clients connected to the object.  It
  140.   is initiated after the client calls OleDelete or the server calls
  141.   OleRevokeServer, OleRevokeServerDoc, or OleRevokeObject.
  142.  
  143.   This is the last time that the receiving object will be called, so all
  144.   resources for the object can be free'd, but we MUST not delete the object
  145.   itself.
  146.  
  147.   WHAT TO DO:
  148.     - Free resources associated with the object
  149.     - Set a flag to indicate 'Release' has been called
  150.     - Nil out any POleClient handles saved in the object
  151.     - Return ole_Ok if successful, Ole_Error_Generic otherwise
  152.  
  153.   NOTE: This is not called Release since it appears at the same scope as
  154.   the Release callback for the Server.
  155. }
  156. function ReleaseObj(Self: POleObject): TOleStatus; export;
  157. var
  158.   SelfPtr: POleObjectObj;
  159. begin
  160.   SelfPtr := PAppObject(Self)^.Owner;
  161.  
  162.   SelfPtr^.Clients[0] := nil;
  163.   SelfPtr^.IsReleased := True;
  164.   ReleaseObj := ole_Ok;
  165. end;
  166.  
  167. { Handles the Show callback.  This gets called when we should make the 
  168.   object visible by making the server window visible and possibly scroling
  169.   the object into view.  If the object is selectable, select it as well.
  170.   'TakeFocus' indicates whether the server should set focus to itself.
  171.  
  172.   WHAT TO DO:
  173.     - Show the window(s) if not visible
  174.     - Scroll 'OleObject' into view and select it if possible
  175.     - If 'TakeFocus' is True, call SetFocus with the main window handle
  176.     - Return ole_Ok if successful, Ole_Error_Generic otherwise
  177. }
  178. function Show(Self: POleObject; TakeFocus: Bool): TOleStatus; export;
  179. begin
  180.   { In our case all we need to do is request that the window is showing
  181.   }
  182.   Application^.MainWindow^.Show(sw_ShowNormal);
  183.  
  184.   if TakeFocus then
  185.     SetFocus(Application^.MainWindow^.HWindow);
  186.  
  187.   Show := ole_Ok;
  188. end;
  189.  
  190. { Handles the DoVerb callback.  The client application has called
  191.   OleActivate on an embedded object and requests an action on the object.
  192.   The action is specified by the verb identifier 'Verb'.  This server
  193.   only understands EDIT and PLAY:  all we do for PLAY is beep, and for
  194.   EDIT we bring up the server and let the user edit the specified object.
  195.  
  196.   PARAMETERS:
  197.     - 'Verb' is the index to the verb to execute
  198.     - 'Show' indicates if the server should show the object or 
  199.       remain in its current state
  200.     - 'Focus' indicates if the server should take the focus
  201.  
  202.   WHAT TO DO:
  203.     - For PLAY verb, a server doesn't usually show its window or affect the
  204.       focus
  205.     - For EDIT verb, show the server's window and object if 'Show' and
  206.       take the focus if 'Focus'
  207.     - Return ole_Ok if successful, Ole_Error_DoVerb otherwise
  208. }
  209. function DoVerb(Self: POleObject; Verb: Word; Show, Focus: Bool): TOleStatus; export;
  210. begin
  211.   case TVerb(Verb) of
  212.     VerbEdit:
  213.       { The easiest way to show the server's window is to send the
  214.         object a 'Show' message.  Note how we access the Object's
  215.         callback list directly.
  216.       }
  217.       if Show then
  218.         DoVerb := Self^.lpvtbl^.Show(Self, Focus)
  219.       else
  220.         DoVerb := ole_Ok;
  221.  
  222.     VerbPlay:
  223.       begin
  224.         MessageBeep(0);
  225.         MessageBeep(0);
  226.  
  227.         DoVerb := ole_Ok;
  228.       end;
  229.   else
  230.     DoVerb := Ole_Error_DoVerb;
  231.   end;
  232. end;
  233.  
  234. { Handles the GetData callback.  We are requested to supply data for
  235.   the object in a specific format, such as Native or cf_MetaFilePict.
  236.   In general, you should handle the same data formats that you put on
  237.   the clipboard when the object was embedded/linked.  These should be
  238.   the same formats that are returned by EnumFormats callback.
  239.  
  240.   Requests for GetData occur any time that the client needs to display
  241.   an object, or when the data must be written to a client file.
  242. }
  243. function GetData(Self: POleObject; Format: TOleClipFormat;
  244.   var Handle: THandle): TOleStatus; export;
  245. var
  246.   App    : POleApp;
  247.   Stat   : TOleStatus;
  248.   SelfPtr: POleObjectObj;
  249. begin
  250.   SelfPtr:= PAppObject(Self)^.Owner;
  251.   App    := POleApp(Application);
  252.  
  253.   Stat := ole_Ok;
  254.   if Format = App^.cfNative then
  255.     Handle := SelfPtr^.GetNativeData
  256.   else
  257.     if Format = App^.cfOwnerLink then
  258.       Handle := SelfPtr^.GetLinkData
  259.     else
  260.       if Format = cf_Bitmap then
  261.         Handle := SelfPtr^.GetBitmapData
  262.       else
  263.         if Format = cf_MetaFilePict then
  264.           Handle := SelfPtr^.GetMetafilePicture
  265.         else
  266.           Stat := Ole_Error_Format;
  267.  
  268.   if  Stat = ole_Ok then
  269.     if Handle = 0 then
  270.       Stat := Ole_Error_Memory;
  271.  
  272.   GetData := Stat;
  273. end;
  274.  
  275. { Handles the SetData callback.  This gets called to provide the server 
  276.   with the data for an object that is embedded in a client.  This routine
  277.   gets called after the server has received an 'Edit' message.  This is
  278.   always called before 'DoVerb' and 'Show'.
  279.  
  280.   WHAT TO DO:
  281.     - If the data format isn't supported, return Ole_Error_Format
  282.     - Lock down the memory to get a pointer to the data, returning
  283.       Ole_Error_Memory if GlobalLock returns NULL
  284.     - Copy the data to the object indicated by 'Self'
  285.     - Unlock the memory and call GlobalFree on the handle (you are
  286.       responsible for the memory!)
  287.     - Return ole_Ok
  288. }
  289. function SetData(Self: POleObject; Format: TOleClipFormat;
  290.   Data: THandle): TOleStatus; export;
  291. var
  292.   App    : POleApp;
  293.   SelfPtr: POleObjectObj;
  294.   DataPtr: PNative;
  295. begin
  296.   SelfPtr:= PAppObject(Self)^.Owner;
  297.   App    := POleApp(Application);
  298.  
  299.   if Format <> App^.cfNative then
  300.     SetData := Ole_Error_Format   { Data isn't in Native format }
  301.   else
  302.   begin
  303.     DataPtr := PNative(GlobalLock(Data));
  304.  
  305.     if DataPtr = nil then
  306.       SetData := Ole_Error_Memory
  307.     else
  308.     begin
  309.       SelfPtr^.Native := DataPtr^;
  310.  
  311.       GlobalUnlock(Data);
  312.       GlobalFree(Data);    
  313.       SetData := ole_Ok;
  314.     end;
  315.   end;
  316. end;
  317.  
  318. { Handles the SetTargetDevice callback.  Not supported; always returns
  319.   Ole_Error_Generic.
  320. }
  321. function SetTargetDevice(Self: POleObject;
  322.   TargetDevice: THandle): TOleStatus; export;
  323. begin
  324.   SetTargetDevice := Ole_Error_Generic;
  325. end;
  326.  
  327. { Handles the SetBounds callback.  Not supported; always returns
  328.   Ole_Error_Generic. 
  329. }
  330. function SetBounds(Self: POleObject; var Bounds: TRect): TOleStatus; export;
  331. begin
  332.   SetBounds := Ole_Error_Generic;
  333. end;
  334.  
  335. { Handles the EnumFormats callback.  The client has requested that we 
  336.   enumerate all clipboard formats that we support for the object 'Self'.
  337.   The server library will make multiple calls until we return the format
  338.   that the server library is looking for
  339.  
  340.   PARAMETERS:
  341.     - 'Format' is the last format returned by this method. if it is 0 then
  342.       this is the first call to the method for this series
  343.  
  344.   We terminate the query by returning NULL.
  345.  
  346.   NOTE: We *must* return the formats in the same order as the order that
  347.         data is placed on the clipboard!
  348. }
  349. function EnumFormats(Self: POleObject;
  350.   Format: TOleClipFormat): TOleClipFormat; export;
  351. var
  352.   App    : POleApp;
  353.   SelfPtr: POleObjectObj;
  354. begin
  355.   App := POleApp(Application);
  356.  
  357.   { If 'Format' is 0 that indicates the client wants us to return the
  358.     first format
  359.   }
  360.   if Format = 0 then
  361.     EnumFormats := App^.cfNative
  362.   else
  363.     if Format = App^.cfNative then
  364.       EnumFormats := App^.cfOwnerLink
  365.     else
  366.       if Format = App^.cfOwnerLink then
  367.         EnumFormats := cf_MetaFilePict
  368.       else
  369.         if Format = cf_MetaFilePict then
  370.           EnumFormats := cf_Bitmap
  371.         else
  372.           EnumFormats := 0;
  373. end;
  374.  
  375. { Handles the SetColorScheme callback.  Not supported, always returns 
  376.   Ole_Error_Generic. 
  377. }
  378. function SetColorScheme(Self: POleObject;
  379.   var Palette: TLogPalette): TOleStatus; export;
  380. begin
  381.   SetColorScheme := Ole_Error_Generic;
  382. end;
  383.  
  384.  
  385. { TOleObjectObj Methods }
  386.  
  387. { Constructs an instance of the TOleObjectObj.
  388. }
  389. constructor TOleObjectObj.Init;
  390. begin
  391.   AppObject.OleObject.lpvtbl := @OleObjectVTbl;
  392.   AppObject.Owner            := @Self;
  393.  
  394.   Native.NativeType:= ObjEllipse;
  395.   Native.Version   := 1;
  396.   Clients[0]       := nil;
  397.   IsReleased       := False;
  398. end;
  399.  
  400. { Constructs the Ole Object by loading it from the given stream.
  401. }
  402. constructor TOleObjectObj.Load(var S: TStream);
  403. var
  404.   NewType: TNativeType;
  405. begin
  406.   AppObject.OleObject.lpvtbl := @OleObjectVTbl;
  407.   AppObject.Owner            := @Self;
  408.  
  409.   Native.NativeType:= ObjEllipse;
  410.   Native.Version   := 1;
  411.   Clients[0]       := nil;
  412.   IsReleased       := False;
  413.  
  414.   S.Read(NewType, SizeOf(NewType));
  415.   PServerWindow(Application^.MainWindow)^.ShapeChange(NewType);
  416.   Native.NativeType := TNativeType(NewType);
  417.   S.Read(Native.Version, SizeOf(Native.Version)); 
  418. end;
  419.  
  420. { Stores the Ole Object onto the given stream.
  421. }
  422. procedure TOleObjectObj.Store(var S: TStream);
  423. begin
  424.   S.Write(Native.NativeType, SizeOf(Native.NativeType));
  425.   S.Write(Native.Version,    SizeOf(Native.Version)); 
  426. end;
  427.  
  428. { Gets the 'NativeType' field of the Native instance variable
  429.   and returns it.
  430. }
  431. function TOleObjectObj.GetType: TNativeType;
  432. begin
  433.   GetType := Native.NativeType;
  434. end;
  435.  
  436. { Sets the 'NativeType' field of the Native instance variable and calls
  437.   ObjectChanged to register the change.
  438. }
  439. procedure TOleObjectObj.SetType(NewType: TNativeType);
  440. begin
  441.   Native.NativeType := NewType;
  442.   ObjectChanged;
  443. end;
  444.  
  445. { Responds to changes in a linked object by sending each of the clients
  446.   we are linked to an Ole_Changed message.
  447. }
  448. procedure TOleObjectObj.ObjectChanged;
  449. var
  450.   I: Integer;
  451. begin
  452.   { Call the object through its callback function
  453.   }
  454.   I := 0;
  455.   while Clients[I] <> nil do
  456.   begin
  457.     Clients[I]^.lpvtbl^.CallBack(Clients[I], Ole_Changed, @AppObject);
  458.     inc(I);
  459.   end;
  460.  
  461.   { Mark the document as changed
  462.   }
  463.   POleApp(Application)^.Server^.Document^.IsDirty := True;
  464. end;
  465.  
  466. { Adds a link to another client.
  467. }
  468. procedure TOleObjectObj.AddClientLink(OleClient: POleClient);
  469. var
  470.   I: Integer;
  471. begin
  472.   { We always append clients to the end of the list
  473.   }
  474.   I := 0;
  475.   while (Clients[I] <> nil) and (I < MaxLinks-1) do
  476.     inc(I);
  477.  
  478.   if (Clients[I] = nil) then
  479.   begin
  480.     Clients[I]  := OleClient;
  481.     Clients[I+1]:= nil;  { Terminator }
  482.   end;
  483. end;
  484.  
  485. { Draws the type specified by the 'NativeType' field of 'Native' using the
  486.   device context that is passed in.
  487. }
  488. procedure TOleObjectObj.Draw(ADC: HDC);
  489. const
  490.   Pts: array [0..3] of TPoint = ((X:ObjWidth div 2; Y:0),
  491.                                  (X:0;              Y:ObjHeight - 1),
  492.                                  (X:ObjWidth - 1;   Y:ObjHeight - 1),
  493.                                  (X:ObjWidth div 2; Y:0)
  494.                                 );
  495. var
  496.   OldBrush : HBrush;
  497.   OldPen   : HPen;
  498. begin
  499.   OldBrush:= SelectObject(ADC, CreateSolidBrush(RGB(0, 0, 255)));
  500.   OldPen  := SelectObject(ADC, GetStockObject(Null_Pen));
  501.  
  502.   case Native.NativeType of
  503.     ObjEllipse:
  504.       Ellipse(ADC, 0, 0, ObjWidth, ObjHeight);
  505.     ObjRect:
  506.       Rectangle(ADC, 0, 0, ObjWidth, ObjHeight);
  507.     ObjTriangle:
  508.       Polygon(ADC, Pts, 4);
  509.   end;
  510.  
  511.   DeleteObject(SelectObject(ADC, OldBrush));
  512.   SelectObject(ADC, OldPen);
  513. end;
  514.  
  515. { Returns a global memory handle that contains the native data for the
  516.   receiver.  This handle can be used to set the Native clipboard data 
  517.   format.
  518. }
  519. function TOleObjectObj.GetNativeData: THandle;
  520. var
  521.   DataHdl : THandle;
  522.   DataPtr : PNative;
  523. begin
  524.   DataHdl := GlobalAlloc(gmem_DdeShare, SizeOf(Native));
  525.  
  526.   if DataHdl <> 0 then
  527.   begin
  528.     DataPtr := PNative(GlobalLock(DataHdl));
  529.     DataPtr^:= Native;
  530.     GlobalUnlock(DataHdl);
  531.   end;
  532.   GetNativeData := DataHdl;
  533. end;
  534.  
  535. { Returns a global memory handle suitable for pasting to the clipboard
  536.   that contains three fields:
  537.  
  538.   - Class name
  539.   - Document name (typically a fully qualified path name that identifies
  540.     the file containing the document)
  541.   - Item name (uniquely identifies the part of the document that is defined
  542.     as an object)
  543.  
  544.   The class name and document name are null terminated, and the item name
  545.   has two terminating null characters, e.g. CNAME#0DNAME#0INAME#0#0
  546.  
  547.   NOTE: Item names are assigned by the server. Since we have only 1 object
  548.         per document, we always use the same name ('1'). most applications
  549.         would use a different strategy, e.g. 'Object1', 'Object2', etc.
  550.  
  551.   Since 'ObjectLink' and 'OwnerLink' formats contain the same information
  552.   the handle that is returned can be used for both clipboard formats
  553. }
  554. function TOleObjectObj.GetLinkData: THandle;
  555. var
  556.   DataHdl: THandle;
  557.   DataPtr: PChar;
  558.   Doc    : POleDocument;
  559.   DocNameLen, ClassKeyLen, Len: Integer;
  560. begin
  561.   Doc := POleApp(Application)^.Server^.Document;
  562.  
  563.   DocNameLen := StrLen(Doc^.Name);
  564.   ClassKeyLen:= StrLen(ClassKey);        
  565.   Len        := ClassKeyLen + DocNameLen + StrLen('1') + 4;   { 4 nulls }
  566.  
  567.   DataHdl := GlobalAlloc(gmem_DdeShare, Len);
  568.  
  569.   if DataHdl <> 0 then
  570.   begin
  571.     DataPtr := GlobalLock(DataHdl);
  572.   
  573.     { Write class name, then the doc name, and then the item name (always
  574.       '1').  Then, append the final NUL.
  575.     }
  576.     StrCopy(DataPtr, ClassKey);
  577.     DataPtr := DataPtr + ClassKeyLen + 1;
  578.     StrCopy(DataPtr, Doc^.Name);
  579.     DataPtr := DataPtr + DocNameLen + 1;
  580.     StrCopy(DataPtr, '1');
  581.     DataPtr[2] := #0;
  582.   
  583.     GlobalUnlock(DataHdl);
  584.   end;
  585.  
  586.   GetLinkData := DataHdl;
  587. end;
  588.  
  589. { Converts a width and height from device units to mm_HiMetric units,
  590.   which are required by the OLE libraries
  591. }
  592. procedure SizeToHiMetric(var Width, Height: Integer);
  593. const
  594.   HiMetricPerInch : Longint = 2540;
  595. var
  596.   ADC: HDC;
  597.   DpiX, DpiY: Integer;
  598. begin
  599.   ADC := GetDC(0);   { Gets a screen DC }
  600.  
  601.   DpiX := GetDeviceCaps(ADC, LogPixelsX);
  602.   DpiY := GetDeviceCaps(ADC, LogPixelsY);
  603.  
  604.   Width := round(Width  * HiMetricPerInch / DpiX);
  605.   Height:= round(Height * HiMetricPerInch / DpiY);
  606.  
  607.   ReleaseDC (0, ADC);
  608. end;
  609.  
  610. { Creates and returns a Metafile Pict which represents the current 
  611.   object.
  612. }
  613. function TOleObjectObj.GetMetafilePicture: THandle;
  614. var
  615.   PictPtr: PMetaFilePict;
  616.   PictHdl: THandle;          
  617.   MFHdl  : THandle;
  618.   ADC    : HDC;
  619.   Width  : Integer;
  620.   Height : Integer;
  621. begin
  622.   ADC   := CreateMetaFile(nil);
  623.   Width := 100;
  624.   Height:= 100;
  625.  
  626.   { Draw the object into the metafile
  627.   }
  628.   SetWindowOrg(ADC, 0, 0);
  629.   SetWindowExt(ADC, Width, Height);
  630.   Draw(ADC);
  631.  
  632.   { Get the handle to the metafile.
  633.   }
  634.   MFHdl := CloseMetaFile(ADC);
  635.  
  636.   { Allocate the metafile picture
  637.   }
  638.   PictHdl := GlobalAlloc(gmem_DDEShare, SizeOf(TMetaFilePict));
  639.  
  640.   if PictHdl <> 0 then
  641.   begin
  642.     SizeToHiMetric(Width, Height);
  643.     PictPtr := PMetaFilePict(GlobalLock(PictHdl));
  644.   
  645.     PictPtr^.mm   := mm_Anisotropic;
  646.     PictPtr^.hMF  := MFHdl;
  647.     PictPtr^.xExt := Width;
  648.     PictPtr^.yExt := Height;
  649.  
  650.     GlobalUnlock(PictHdl);
  651.   end;
  652.  
  653.   GetMetafilePicture := PictHdl;
  654. end;
  655.  
  656. { Creates and returns an image of the Object as a Bitmap.
  657. }
  658. function TOleObjectObj.GetBitmapData: HBitmap;
  659. var
  660.   AWnd      : HWnd;
  661.   ADC       : HDC;      
  662.   AMemDC    : HDC;      
  663.   ABitmap   : HBitmap; 
  664.   OldBitmap : HBitmap; 
  665.   Width     : Integer;
  666.   Height    : Integer;
  667. begin
  668.   AWnd  := Application^.MainWindow^.HWindow;
  669.   ADC   := GetDC(AWnd);
  670.   AMemDC:= CreateCompatibleDC(ADC);
  671.  
  672.   ABitmap   := CreateCompatibleBitmap(ADC, 100, 100);
  673.   OldBitmap := SelectObject(AMemDC, ABitmap);
  674.  
  675.   Width := 100;
  676.   Height:= 100;
  677.  
  678.   ReleaseDC(AWnd, ADC);
  679.   PatBlt(AMemDC, 0, 0, Width, Height, Whiteness);
  680.   Draw(AMemDC);
  681.   SelectObject(AMemDC, OldBitmap);
  682.   DeleteDC(AMemDC);
  683.  
  684.   { Convert the width and height to mm_Himetric (all OLE libraries express
  685.     the size of every object in mm_Himetric)
  686.   }
  687.   SizeToHiMetric(Width, Height);
  688.  
  689.   { SetBitmapDimension wants the width and height in .1 millimeter
  690.     units, so we must divide by 10.
  691.   }
  692.   SetBitmapDimension(ABitmap, round(Width / 10), round(Height / 10));
  693.  
  694.   GetBitmapData := ABitmap;
  695. end;
  696.  
  697. { Initialize the VTbl for the Server.  Create thunks for OleObjectObj callback
  698.   tables.
  699. }
  700. function TOleObjectObj_InitVTBL(Inst: THandle): Boolean;
  701. begin
  702.   @OleObjectVTbl.QueryProtocol   := MakeProcInstance(@QueryProtocol,   Inst);
  703.   @OleObjectVTbl.Release         := MakeProcInstance(@ReleaseObj,      Inst);
  704.   @OleObjectVTbl.Show            := MakeProcInstance(@Show,            Inst);
  705.   @OleObjectVTbl.DoVerb          := MakeProcInstance(@DoVerb,          Inst);
  706.   @OleObjectVTbl.GetData         := MakeProcInstance(@GetData,         Inst);
  707.   @OleObjectVTbl.SetData         := MakeProcInstance(@SetData,         Inst);
  708.   @OleObjectVTbl.SetTargetDevice := MakeProcInstance(@SetTargetDevice, Inst);
  709.   @OleObjectVTbl.SetBounds       := MakeProcInstance(@SetBounds,       Inst);
  710.   @OleObjectVTbl.EnumFormats     := MakeProcInstance(@EnumFormats,     Inst);
  711.   @OleObjectVTbl.SetColorScheme  := MakeProcInstance(@SetColorScheme,  Inst);
  712.  
  713.   TOleObjectObj_InitVTbl := (@OleObjectVTbl.QueryProtocol <> nil) and
  714.                             (@OleObjectVTbl.Release <> nil) and
  715.                             (@OleObjectVTbl.Show <> nil) and
  716.                             (@OleObjectVTbl.DoVerb <> nil) and
  717.                             (@OleObjectVTbl.GetData <> nil) and
  718.                             (@OleObjectVTbl.SetData <> nil) and
  719.                             (@OleObjectVTbl.SetTargetDevice <> nil) and
  720.                             (@OleObjectVTbl.SetBounds <> nil) and
  721.                             (@OleObjectVTbl.EnumFormats <> nil) and
  722.                             (@OleObjectVTbl.SetColorScheme <> nil);
  723. end;
  724.  
  725. end.